// Setup basic express server
const fs = require('fs');
const http = require('http');
const https = require('https');
const express = require('express');
const socketIo = require('socket.io');
const path = require('path');
const selfsigned = require('selfsigned');
const crypto = require('crypto');
const namespace = require('socket.io/lib/namespace');

const app = express();

// socketio服务器版本
console.log('server version: 2.5.1');
console.log('clinet version: socketio_2.x');
const httpPort = 3000;
const httpsPort = 3101;

// 定义证书和密钥的路径
const certDir = path.join(__dirname, 'certs');
const keyPath = path.join(certDir, 'key.pem');
const certPath = path.join(certDir, 'cert.pem');

// 工具：读取位数（私钥）
function getPrivateKeyBits(pem) {
  try {
    const keyObj = crypto.createPrivateKey(pem);
    const details = keyObj.asymmetricKeyDetails || {};
    return details.modulusLength || 0;
  } catch (_) {
    return 0;
  }
}

// 工具：读取位数（证书公钥）
function getCertPublicKeyBits(pem) {
  try {
    const x509 = new crypto.X509Certificate(pem);
    const pub = x509.publicKey;
    const details = pub.asymmetricKeyDetails || {};
    return details.modulusLength || 0;
  } catch (_) {
    return 0;
  }
}

// 工具：生成强度合规的自签证书
function generateStrongSelfSigned() {
  const attrs = [{ name: 'commonName', value: 'localhost' }];
  return selfsigned.generate(attrs, {
    days: 365,
    keySize: 2048,
    algorithm: 'sha256',
    extensions: [
      { name: 'basicConstraints', cA: false },
      { name: 'keyUsage', digitalSignature: true, keyEncipherment: true },
      { name: 'extKeyUsage', serverAuth: true, clientAuth: true },
      {
        name: 'subjectAltName',
        altNames: [
          { type: 2, value: 'localhost' },
          { type: 7, ip: '127.0.0.1' },
          { type: 7, ip: '::1' }
        ]
      }
    ]
  });
}

// 准备 httpsOptions：缺失/过弱时重建
let httpsOptions;
let needRegen = false;
let keyPem = fs.existsSync(keyPath) ? fs.readFileSync(keyPath) : null;
let certPem = fs.existsSync(certPath) ? fs.readFileSync(certPath) : null;

if (!keyPem || !certPem) {
  needRegen = true;
} else {
  const keyBits = getPrivateKeyBits(keyPem);
  const certBits = getCertPublicKeyBits(certPem);
  if (!keyBits || keyBits < 2048) needRegen = true;
  if (!certBits || certBits < 2048) needRegen = true;
}

if (needRegen) {
  const pems = generateStrongSelfSigned();
  if (!fs.existsSync(certDir)) fs.mkdirSync(certDir, { recursive: true });
  fs.writeFileSync(keyPath, pems.private);
  fs.writeFileSync(certPath, pems.cert);
  keyPem = Buffer.from(pems.private);
  certPem = Buffer.from(pems.cert);
  console.log('[TLS] Generated new RSA-2048 self-signed certificate.');
}

httpsOptions = {
  key: keyPem,
  cert: certPem,
  minVersion: 'TLSv1.2'
};
// 创建 HTTP 服务器
const httpServer = http.createServer(app);

 // 创建 HTTPS 服务器
const httpsServer = https.createServer(httpsOptions, app);

// 创建 Socket.IO 实例，绑定到 HTTP 和 HTTPS 服务器
//const io = socketIo();
const io = socketIo(
 // {path : '/chat'}
);
io.attach(httpServer);
io.attach(httpsServer);

// Routing
app.use(express.static(path.join(__dirname, 'public')));

//启动 HTTP 服务器
httpServer.listen(httpPort, () => {
  console.log(`HTTP server listening on port ${httpPort}`);
});

// 启动 HTTPS 服务器
httpsServer.listen(httpsPort, () => {
  console.log(`HTTPS server listening on port ${httpsPort}`);
});

// Chatroom
let numUsers = 0;
let sentMessageCount = 0; // 全局计数器
io.on('connection', (socket) => {
  // console.log('a user connected:', socket.id, socket.handshake.url);
  console.log('a user connected to default namespace:', socket.id, socket.handshake.url);

  // // set_option test  
  // try {
  //   // 直接获取 options
  //   const rawOptions = socket.handshake.query;

  //   console.log('原始options:', rawOptions);
  // } catch(e) {

  //   console.error('配置解析失败:', e.message);
  // }
// set_option test  
// try {
//   // 获取原始options
//   const rawOptions = socket.handshake.query;
  
//   if(rawOptions.options) {
//     // 移除多余空格
//     let cleanStr = rawOptions.options.replace(/\s+/g, '');
//     // 替换单引号为双引号
//     cleanStr = cleanStr.replace(/'/g, '"');
//     // 解析JSON
//     const options = JSON.parse(cleanStr);
//     console.log('解析后的配置:', options);
//   } else {
//     console.log('原始options:', rawOptions);
//   }
// } catch(e) {
//   console.error('配置解析失败:', e.message);
//   console.log('原始query:', socket.handshake.query);
// }

  numUsers++;
  console.log('用户连接，当前用户数:', numUsers);
  let addedUser = false;

   // 处理心跳：监听客户端的 pong 事件
  socket.on('pong', () => {
    console.log(`Received pong from client ${socket.id}`);
  });

  // when the client emits 'new message', this listens and executes
  socket.on('new message', (data) => { 
    // we tell the client to execute 'new message'
    socket.broadcast.emit('new message', { // broadcast是广播，除了自己以外的所有人
      username: socket.username,
      message: data
    });
  
  });

  //   setTimeout(() => {
  //   socket.disconnect(true); // 断开连接
  // }, 5000); 

  
  // setInterval(() => {
  //   socket.emit('response', JSON.stringify({ message: 'default namespace 定时服务器响应' }));
  // }, 10000); // 每10秒发送一次
  // when the client emits 'add user', this listens and executes
  socket.on('add user', (username) => {
    if (addedUser) return;

    // we store the username in the socket session for this client
    socket.username = username;
    
    console.log('用户名:', username);
    console.log('用户名字节长度:', Buffer.from(username).length);
    
    // ++numUsers;
    addedUser = true;

    socket.emit('login', {"numUsers": numUsers});
    const messages1 = [
      {"message": {"username": "robot", "message": "Welcome to the chat room!"}},
    ]

  //   // 计数发送消息
  //   function sendMessages() {
  //     messages1.forEach(function(msg) {
  //       sentMessageCount++; // 递增计数器

  //       // 深拷贝消息对象，避免修改原始数据
  //       const messageWithCount = JSON.parse(JSON.stringify(msg.message));

  //       // 在消息对象中添加计数属性
  //       messageWithCount.count = sentMessageCount;

  //       // 发送包含计数值的消息
  //       socket.emit("login", messageWithCount);

  //       // // 记录日志
  //       // console.log(`已发送消息数量: ${sentMessageCount}`, messageWithCount);

  //       // 动态输出
  //       process.stdout.write(`已发送消息数量: ${sentMessageCount}\r`);

  //    });
  //  }
  //    setInterval(sendMessages, 1000);


    // echo globally (all clients) that a person has connected
    socket.broadcast.emit('user joined', {
      username: socket.username,
      numUsers: numUsers
    });
  });

  // when the client emits 'typing', we broadcast it to others
  socket.on('typing', () => {
    socket.broadcast.emit('typing', {
      username: socket.username
    });
  });

  // when the client emits 'stop typing', we broadcast it to others
  socket.on('stop typing', () => {
    socket.broadcast.emit('stop typing', {
      username: socket.username
    });
  });


  // when the user disconnects.. perform this
  socket.on('disconnect', () => {
    console.log('user disconnected:', socket.id);
    if (addedUser) {
      --numUsers;
      console.log('用户断开，当前用户数:', numUsers);
      // echo globally that this client has left
      socket.broadcast.emit('user left', {
        username: socket.username,
        numUsers: numUsers
      });
    }
  });
});

// 定义命名空间 'nsp_test'
const nspTest = io.of('/nsp_test');

nspTest.on('connection', (socket) => {
  console.log('a user connected to nsp_test namespace:', socket.id, socket.handshake.url);

   // when the client emits 'new message', this listens and executes
  socket.on('new message', (data) => { 
    // we tell the client to execute 'new message'
    socket.broadcast.emit('new message', { // broadcast是广播，除了自己以外的所有人
      username: socket.username,
      message: data
  })
  console.log('Received message in nsp_test namespace:', data, socket.id);
});
  // 定时发送 'response' 事件
  // setInterval(() => {
  //   socket.emit('response', JSON.stringify({ message: 'nsp_test namespace 定时服务器响应' }));
  // }, 10000); // 每10秒发送一次
  socket.on('disconnect', () => {
    console.log('user disconnected from nsp_test namespace:', socket.id);
  });
});
